<?php
/**
 * Created by WuYe.
 * User: '常志明'
 * Date: 2018-10-17 13:53
 * 物业档案
 *
 */

namespace app\index\controller;


use think\File;

class PropertyFiles
{
    const propertyfiles = [
        'userId'=>'',       //用户id usermanage(id)
        'realpath'=>'',     //路径
        'directory'=>'',    //虚拟路径 目录
        'fileName'=>'',     //文件名
        'fileSize'=>'',     //文件大小
        'date'=>'',         //上传日期
    ];

    /**
     *  创建文件夹
     * @param string $id        上级文件夹id
     * @param string $directory 文件虚拟目录
     */
    public static function  createDirectory($id = '', $directory = '')
    {
        if(!empty($perssion = perssion([LOGIN, SHOP])))   //权限判断
            return $perssion;
        if(empty($vars = getInputAll('directory'))) //参数判断
            return RD(PARA_NOT_NULL);

        $result = getFirst(mongo('propertyfiles')->where(['userId'=>cookie('userId')])->where(['directory'=>$vars['directory']])->select());
        if(!empty($result)) {
            return RD(FAIL, '文件夹已经存在');
        }

        $insertData = self::propertyfiles;
        $insertData['userId'] = cookie('userId');
        $insertData['directory'] = $vars['directory'];
        $insertData['date'] = date('Y-m-d');

        mongo('propertyfiles')->insert($insertData);
        return RD(SUCCESS, mongo('propertyfiles')->getLastInsID());
    }

    /**
     * 删除文件夹/文件
     * @param array $directory 文件夹路径  文件目录 ['/a/b/', '/a/b/a.png']
     * @return array
     */
    public static function deleteDirectoryOrFile($directorys  = [])
    {
        if(!empty($perssion = perssion([LOGIN, SHOP])))   //权限判断
            return $perssion;
        if(empty($vars = getInputAll('directorys'))) //参数判断
            return RD(PARA_NOT_NULL);
        foreach ($vars['directorys'] as $directory)
        {
            $dirName = (strlen(dirname($directory)) > 1) ? dirname($directory).'/' : dirname($directory);

            $result = ($directory[strlen($directory) - 1] == '/') ?
                mongo('propertyfiles')->where(['userId'=>cookie('userId')])->where('directory', 'like', '^('.$directory.').*')->select() :
                mongo('propertyfiles')->where(['userId'=>cookie('userId')])->where(['directory'=>$dirName, 'fileName'=>basename($directory)])->select();

            foreach ($result as $file)
            {
                if(!empty($file['realpath'])) {
                    deleteFileIn($file['realpath']);  //删除文件
                }
                mongo('propertyfiles')->where(['id'=>$file['id']])->delete(); //删除目录项
            }
        }
        return RD(SUCCESS);
    }

    /**
     * 重命名文件夹
     * @param string $directory       文件夹路径
     * @param string $newDirectory    新文件夹路径
     */
    public static function renameDirectory($directory = '', $newDirectory = '')
    {
        if(!empty($perssion = perssion([LOGIN, SHOP])))   //权限判断
            return $perssion;
        if(empty($vars = getInputAll('directory', 'newDirectory'))) //参数判断
            return RD(PARA_NOT_NULL);
        $result = mongo('propertyfiles')->where(['userId'=>cookie('userId')])->where('directory', 'like', '^('.$vars['directory'].').*')->select();
        foreach ($result as $file)
        {
            $directory = str_replace($vars['directory'], $vars['newDirectory'], $file['directory']);
            mongo('propertyfiles')->where(['id'=>$file['id']])->update(['directory'=>$directory]);
        }
        return RD(SUCCESS);
    }
    /**
     * 移动文件到文件夹
     * @param array $directorys       文件夹路径   ['/a/b/', '/a/b/a.png']
     * @param string $newDirectory     新文件夹路径
     */
    public static function moveToDirectory($directorys = [], $newDirectory = '')
    {
        if(!empty($perssion = perssion([LOGIN, SHOP])))   //权限判断
            return $perssion;
        if(empty($vars = getInputAll('directorys', 'newDirectory'))) //参数判断
            return RD(PARA_NOT_NULL);
        foreach ($vars['directorys'] as $directory)
        {
            $dirName = (strlen(dirname($directory)) > 1) ? dirname($directory).'/' : dirname($directory);

            $result = ($directory[strlen($directory) - 1] == '/') ?
                mongo('propertyfiles')->where(['userId'=>cookie('userId')])->where('directory', 'like', '^('.$directory.').*')->select() :
                mongo('propertyfiles')->where(['userId'=>cookie('userId')])->where(['directory'=>$dirName, 'fileName'=>basename($directory)])->select();

            foreach ($result as $file)
            {
                $directory_t = str_replace_once($dirName, $vars['newDirectory'], $file['directory']);
                mongo('propertyfiles')->where(['id'=>$file['id']])->update(['directory'=>$directory_t]);
            }

        }
        return RD(SUCCESS);
    }

    /**
     * 上传文件
     * @param string $directory           文件路径 /a/
     * @param string $file                文件内容
     * @param string $relativePath        文件上传路径
     * @param string $chunkSize           每一块的大小
     * @param string $currentChunkSize    当前快的大小
     * @param string $totalSize           总大小
     * @param string $identifier          唯一标识
     * @param string $filename            文件名
     * @param string $totalChunks         总块数
     * @param string $chunkNumber         当前块号
     * @return array
     */
    public static function propertyUploadFile( $file = '', $relativePath = '', $chunkSize = '', $currentChunkSize = '', $totalSize='',$identifier = '', $filename = '', $totalChunks = '', $chunkNumber='')
    {
        if(!empty($perssion = perssion([LOGIN, SHOP])))   //权限判断
            return $perssion;
        if(empty($vars = getInputAll('directory', 'chunkNumber', 'chunkSize','currentChunkSize','totalSize','identifier','filename','totalChunks','relativePath'))) //参数判断
            return RD(PARA_NOT_NULL);

        $file = request()->file('file');
        if(!empty($file)) {
            $file = $file->move(FileSavePath);
            $path = $file->getRealPath();

            //文件大小判断
            if($file->getSize() != $vars['currentChunkSize']) {
                if(file_exists($path)) {
                    unlink($path);
                }  //删除
                return RD(FAIL, '文件传输大小错误');
            }

            $fileInfo = [];

            if(cache($vars['identifier']) != false) {
                $fileInfo = cache($vars['identifier']);
            }
            array_push($fileInfo, ['path'=>$path, 'chunkNumber'=>$vars['chunkNumber']]);
            cache($vars['identifier'], $fileInfo);

            if(count($fileInfo) >= $vars['totalChunks']) {  //合并文件

                //查询文件名
                $filename = $file->getPath().DS.$vars['filename'];       //唯一文件
                $path = $filename;
                $i = 0;
                while (true) {
                    if(!file_exists($filename)) {
                        break;
                    }
                    $filename = substr_replace($path, '('.$i.')', strpos($path, '.'), 0);
                    $i++;
                }
                $vars['filename'] = basename($filename);

                $path = self::mergeFile(cache($vars['identifier']), $filename, $vars['totalChunks']);

                cache($vars['identifier'], NULL);  //清空缓存
                //插入数据
                $insertData = self::propertyfiles;
                $insertData['userId'] = cookie('userId');
                $insertData['directory'] = $vars['directory'];
                $insertData['fileName'] =  $vars['filename'];
                $insertData['fileSize'] =  $vars['totalSize'];
                $insertData['date'] =  date('Y-m-d');

                $insertData['realpath'] = FileDownLoadDomain.$path; //文件访问路径
                mongo('propertyfiles')->insert($insertData);  //插入

                return RD(SUCCESS, $insertData);
            }
            return RD(SUCCESS);  //部分成功
        }
        return RD(FAIL);
    }

    /**
     * 重命名文件名
     * @param string $directory
     * @param string $fileName
     * @param string $newFileName
     */
    public static function renameFile($directory = '', $fileName = '', $newFileName = '')
    {
        if(!empty($perssion = perssion([LOGIN, SHOP])))   //权限判断
            return $perssion;
        if(empty($vars = getInputAll('directory', 'fileName', 'newFileName'))) //参数判断
            return RD(PARA_NOT_NULL);
        mongo('propertyfiles')->where(['userId'=>cookie('userId')])->where(['directory'=>$vars['directory'], 'fileName'=>$vars['fileName']])->update(['fileName'=>$vars['newFileName']]);
        return RD(SUCCESS);
    }

    /**
     * 取消上传
     * @param array $identifiers 文件唯一id  []
     * @return array
     */
    public static function cancelUpload($identifiers = [])
    {
        if(!empty($perssion = perssion([LOGIN, SHOP])))   //权限判断
            return $perssion;
        $identifiers = input('identifiers/a', []);
        foreach ($identifiers as $identifier)
        {
            $fileInfo = cache($identifier);
            if($fileInfo == false)
                continue;
            //删除
            foreach ($fileInfo as $file) {
                unlink($file['path']);   //删除所有临时文件
            }
            cache($identifier, NULL);  //清空缓存
        }
        return RD(SUCCESS);
    }
    /**
     * 获取文件夹或目录
     * @param string $directory    目录
     * @param string $keyword      关键字
     */
    public static function getDirOrFile($directory  = '', $keyword = '')
    {
        if(!empty($perssion = perssion([LOGIN, SHOP])))   //权限判断
            return $perssion;
        if(empty($vars = getInputAll('directory'))) //参数判断
            return RD(PARA_NOT_NULL);
        $keyword = isset($vars['keyword']) ? $vars['keyword'] : '';

        $result = mongo('propertyfiles')->field('directory, fileName, realpath, fileSize, date')
            ->where(['userId'=>cookie('userId')])
            ->where('directory', 'like', '^('.$vars['directory'].')[^/]*/?$')
            ->where(function ($query) use ($keyword) {
                $query->whereOr('directory', 'like', '.*'.$keyword.'.*')
                    ->whereOr('fileName', 'like', '.*'.$keyword.'.*');
            })
            ->select();
        foreach ($result as $key=>$value)
        {
            DArray($result[$key], 'id');  //删除id
            if($value['directory'] != $vars['directory'] && !empty($value['fileName'])) {  //下级文件夹
                unset($result[$key]);
                continue;
            }
            if($value['directory'] == $vars['directory'] && empty($value['fileName'])) {  //文件夹本身
                unset($result[$key]);
                continue;
            }
            $directoryName = explode('/', $result[$key]['directory']);
            $result[$key]['directoryName'] = (count($directoryName) - 2 > 0) ? $directoryName[count($directoryName) - 2] : '';
        }

        $my_sort = function ($a, $b) {
            $avalue = $a['fileName'];
            $bvalue = $b['fileName'];
            if ($avalue == $bvalue)
                return 0;
            return ($avalue < $bvalue)? -1: 1;
        };
        usort($result, $my_sort);  //排序
        return RD(SUCCESS, $result);
    }

    /**
     * 批量下载
     * @param array $directorys  所有文件夹//文件  路径 ['/a/b/', '/a/b/a.png']
     * @return 压缩文件
     */
    public static function downloadFiles($directorys = [])
    {
        if(!empty($perssion = perssion([LOGIN, SHOP])))   //权限判断
            return $perssion;
        if(empty($vars = getInputAll('directorys'))) //参数判断
            return RD(PARA_NOT_NULL);
        $directorys = $vars['directorys'];

        //10天删除
        $dirs = scandir(FileTempPath);
        foreach ($dirs as $file)
        {
            if($file == '.' || $file == '..')
                continue;
            if((time() - filemtime(FileTempPath.$file)) > (60 * 60 * 24 * 10)) {  //10天
                unlink(FileTempPath.$file);
            }
        }
        //单文件下载
        if(count($directorys) == 1 && $directorys[0][strlen($directorys[0]) - 1] != '/') {

            $dirName = (strlen(dirname($directorys[0])) > 1) ? dirname($directorys[0]).'/' : dirname($directorys[0]);
            $result = getFirst(mongo('propertyfiles')->where(['userId'=>cookie('userId')])->where(['directory'=>$dirName, 'fileName'=>basename($directorys[0])])->select());
            if(!empty($result)) {
                return RD(SUCCESS, $result['realpath']);
            }
        } else {
            $zipName = FileTempPath.uuid().'批量下载.zip';
            $zip = new \ZipArchive;//使用本类，linux需开启zlib，windows需取消php_zip.dll前的注释
            if ($zip->open($zipName, \ZIPARCHIVE::OVERWRITE | \ZIPARCHIVE::CREATE)!==TRUE) {
                return RD(FAIL, '无法打开文件，或者文件创建失败');
            }
            //所有目录下文件
            foreach ($directorys as $directory)
            {
                $dirName = (strlen(dirname($directory)) > 1) ? dirname($directory).'/' : dirname($directory);
                $result = ($directory[strlen($directory) - 1] == '/') ?
                    mongo('propertyfiles')->where(['userId'=>cookie('userId')])->where('directory', 'like', '^('.$directory.').*')->select() :
                    mongo('propertyfiles')->where(['userId'=>cookie('userId')])->where(['directory'=>$dirName, 'fileName'=>basename($directory)])->select();

                foreach ($result as $file) {
                    if(!empty($file['realpath'])) {
                        $path = str_replace(FileDownLoadDomain, "",$file['realpath']);
                        if(file_exists($path)){
                            $zip->addFile($path, basename($path));//第二个参数是放在压缩包中的文件名称，如果文件可能会有重复，就需要注意一下
                        }
                    }
                }
            }
            $zip->close();//关闭
            if(!file_exists($zipName)){
                return RD(FAIL, '无法找到文件');
            }
            return RD(SUCCESS, FileDownLoadDomain.$zipName);
        }
    }
    /**
     *  合并文件
     * @param array $fileInfo    上传文件信息
     * @param string $filename   文存储路径绝对路径
     * @param string $totalChunks 总块数
     * @return string            文件存储路径
     */
    public static function mergeFile($fileInfo , $filename, $totalChunks)
    {
        //合并
        for($i = 1; $i <= $totalChunks; $i++)
        {
            $path = '';
            foreach ($fileInfo as $file) {
                if($file['chunkNumber'] == $i) {
                    $path = $file['path'];
                    break;
                }
            }
            file_put_contents($filename, file_get_contents($path),  FILE_APPEND);  //存储文件
            unlink($path);                                                         //删除临时文件
        }
        return $filename;
    }
}